<script setup>
	// setup 执行时机，比beforeCreate还要早
	// setup 函数中获取不到this，this是undefind，以后的setup中不要用this
	// setup 中的内容需要return，才能在模板中应用
	
	// reactive: 接收一个对象类型的数据，返回一个响应式的对象
	// ref: 可以接收简单类型 或者 对象类型的数据，返回一个响应式的对象
	// computed: 计算属性
	// watch: 监听响应式数据
	import {reactive, ref, computed, watch, onMounted} from 'vue';
	
	let data = reactive({
		message: 'vue3',
		value: 3
	});
	const doData = () => {
		data.message = data.message==='VUE3' ? 'vue3' : 'VUE3';
		data.value = 3;
		// console.log(data.message, data.value);
	}
	
	let count = ref(1);
	// count 在原来数据的基础上，包了一个对象
	// 在script脚本中需要通过count.value来访问这个数据， 在template中不需要加.value
	const add = () => {
		count.value++;
	}
	
	// const 计算属性 = computed(()=>{return 计算结果})
	const list = ref([1,2,3,4,5,6,7,8,9]);
	// 找出list中的偶数
	const computedList = computed(() =>{
		return list.value.filter(v => v%2===0);
	});
	/**
	 *  通常不修改计算属性的，特殊情况如全选 反选，可以使用get set方法
	 *  const computedList = computed({
	 * 		get: ()=>{},
	 * 		set: (value)=>{}
	 *  })
	 */
	
	const randomList = ()=> {
		const temps = [];
		for (let i=0; i<20; i++) {
			temps.push(parseInt(Math.random()*10));
		}
		list.value = temps;
	}
	
	// 监听单个数据的变化 
	watch(count, (newValue, oldValue) => {
		console.log(newValue, oldValue);
	})
	
	const name = ref('my name');
	// 监听多个数据的变化
	watch([count, name], ([newCount, newName], [oldCount, oldName]) => {
		console.log(newCount, newName, oldCount, oldName);
	});

	// 深度监听 与 立刻执行
	watch(list, (newList, oldList)=> {
		console.log(newList, oldList);
	}, {
		immediate: true, // 让watch在一进入页面是就触发第一次
		deep: true, // 深层监听，监听复杂类型中的数据变化
	});
	
	// 精确监听对象中的某个数据的变化
	watch(()=>data.message, (newMessage, oldMessage)=> {
		console.log(newMessage, oldMessage);
	})
	
	// vue3生命周期
	/**
	 *  选项式api						组合式api
	 * beforeCreate/created				setup
	 * beforeMount						onBeforeMount
	 * mounted							onMounted
	 * beforeUpdate						onBeforedUpdate
	 * updated							onUpdated
	 * beforeUnmount					onBeforeUnmount
	 * unmounted						onUnmounted
	 * 
	 */
	
	// beforeCreate/created中的需要执行的代码直接写，直接调用
	const getList= () =>{}
	getList();
	
	// mounted中的不同逻辑可以分开写
	onMounted(()=>{
		console.log('mounted生命周期函数逻辑1')
	})
	onMounted(()=>{
		console.log('mounted生命周期函数逻辑2')
	})
	
	/**
	 * 父 传 子
	 * 1、在父组件 通过添加属性的方式传值
	 * 2、在子组件 通过props接收
	 */
	import Son from '@/components/son.vue'
	
	const changeDataMessage = (msg)=> {
		data.message = msg;
	}
	
	// ref获取真实的dom对象
	// 1、申明一个ref。2、在template中使用ref="自定义的ref名字" 
	// 渲染完成后能过 .value访问绑定的元素
	const inputRef = ref(null);
	onMounted(()=>{
		inputRef.value.focus();
	})
	const inputBlur = ()=>{
		console.log(inputRef.value.value);
	}
	
	const sonRef = ref(null);
	onMounted(()=>{
		console.log(sonRef.value);
	})
	// 父组件 使用ref调用子组件中的方法，
	// 需要在子组件中使用defineExpose把方法暴露出来
	const parentClickSon = ()=> {
		sonRef.value.clickMessage();
	}
	
	// 跨层级传递数据 provide 与 inject
	import {provide} from 'vue';
	provide('name', 'value');
	provide('changeName', (newName)=>{
		console.log(newName);
	})
	
	// vue3.3+ 新特性 defineOptions 定义name
	/**
	 * 
	 * defineOptions({
	 *	name: 'com'
	 * })
	 * 
	 */
	
	// vue3.3+ 新特性 defindModel
</script>

<template>
	<div>
		<button @click="doData">{{data.message}}</button>
	</div>
	
	<div>
		<button @click="add">{{count}}</button>	
	</div>
	
	<div>
		{{list}}
	</div>
	<div>
		{{computedList}}
	</div>
	
	<button @click="randomList">Random</button>
	
	
	<!--子组件 -->
	<Son ref="sonRef" 
	:message="data.message" 
	@changeMessage="changeDataMessage"/>
	
	<div>
		<input ref="inputRef" @blur="inputBlur"/>
		<button @click="parentClickSon">父组件调用子组件的方法</button>
	</div>
</template>

<style scoped>

</style>
